// depends on "primitive_datatypes.h"
// depends on "Vector.h"

#pragma once

struct Mat4x4{
	union{
		struct {
			Number _11, _12, _13, _14;	// / _11 , _12 , _13 , _14 \ //
			Number _21, _22, _23, _24;	// | _21 , _22 , _23 , _24 |
			Number _31, _32, _33, _34;	// | _31 , _32 , _33 , _34 |
			Number _41, _42, _43, _44;	// \ _41 , _42 , _43 , _44 /

		};
		Number _m[4][4];
		Number _data[16];
	};

	Mat4x4();
	Mat4x4( Const Number* axData);
	Mat4x4( Const Mat4x4& );
	Mat4x4( Number _11, Number _12, Number _13, Number _14,
		 Number _21, Number _22, Number _23, Number _24,
		 Number _31, Number _32, Number _33, Number _34,
		 Number _41, Number _42, Number _43, Number _44 );
	Mat4x4& operator = (Const Mat4x4& old);

	// access grants
    Number& operator () ( Int Row, Int Col );
    Number  operator () ( Int Row, Int Col ) Const;

	// casting operators
    operator Number* ();
    operator Const Number* () Const;

	// assignment operators
	Mat4x4&	operator *= ( Const Mat4x4& );
	Mat4x4&	operator += ( Const Mat4x4& );
	Mat4x4&	operator -= ( Const Mat4x4& );
	Mat4x4&	operator *= ( Number );
	Mat4x4&	operator /= ( Number );

	// unary operators
	Mat4x4		operator + () Const;
	Mat4x4		operator - () Const;

	// binary operators
    Mat4x4		operator * ( Const Mat4x4& ) Const;
    Mat4x4		operator + ( Const Mat4x4& ) Const;
    Mat4x4		operator - ( Const Mat4x4& ) Const;
    Mat4x4		operator * ( Number ) Const;
    Mat4x4		operator / ( Number ) Const;

    friend Mat4x4 operator * ( Number, Const Mat4x4& );

    Bool	operator == ( Const Mat4x4& ) Const;
    Bool	operator != ( Const Mat4x4& ) Const;

	// other member methods
	Mat4x4&	negate();
	Mat4x4		negated();
	Mat4x4&	transpose();
	Mat4x4		transposed();
	Mat4x4&	inverse();
	Number	determinat();

	// static functions	
	static void Identity(Mat4x4& mat);
	static Mat4x4	Identity(void);
	static void	Inverse(Mat4x4& mat);
	static void Translate(Number x, Number y, Number z, Mat4x4& mat);
	static Mat4x4	Translate(Number x, Number y, Number z);
	static void Translate(Vec3, Mat4x4& mat);
	static Mat4x4	Translate(Vec3);
	static void Scale(Number factor,Mat4x4& mat);
	static Mat4x4	Scale(Number factor);
	static void Scale(Number factorX, Number factorY, Number factorZ, Mat4x4& mat);
	static Mat4x4	Scale(Number factorX, Number factorY, Number factorZ);
	static void RotateX(Number angle, Mat4x4& mat);
	static Mat4x4	RotateX(Number angle);
	static void RotateY(Number angle, Mat4x4& mat);
	static Mat4x4	RotateY(Number angle);
	static void RotateZ(Number angle, Mat4x4& mat);
	static Mat4x4	RotateZ(Number angle);
	static void Rotate(Number roll, Number pitch, Number yaw, Mat4x4& mat);
	static Mat4x4	Rotate(Number roll, Number pitch, Number yaw);
};